/**
 * @file	spi.h
 * @author	chipsea
 * @brief	Contains all functions support for spi driver
 * @version	0.1
 * @date	2020-11-30
 * @copyright Copyright (c) 2020, CHIPSEA Co., Ltd.
 * @note
 */
#ifndef _SPI_H_
#define _SPI_H_

#include "types.h"
#include "gpio.h"
#include "clock.h"


#define SPI_DMAC_CH     DMA_CH_0

#define REG_PERIPHERAL_MASTER_SELECT    (*((volatile unsigned int *) 0x4000302C))
#define SPI_MASTER_SELECT(num)	        ((REG_PERIPHERAL_MASTER_SELECT) |= (BIT(num) | BIT(num + 4)))
#define SPI_SLAVE_SELECT(num)	        ((REG_PERIPHERAL_MASTER_SELECT) &= ~(BIT(num)))

#define  ENABLE_SPI           Ssix->SSIEN = 1
#define  DISABLE_SPI          Ssix->SSIEN = 0
#define  NUMBER_DATA_RX_FIFO  Ssix->RXFLR
#define  NUMBER_DATA_TX_FIFO  Ssix->TXFLR

#define  SPI_BUSY             0x1
#define  TX_FIFO_NOT_FULL     0x2
#define  TX_FIFO_EMPTY        0x4
#define  RX_FIFO_NOT_EMPTY    0x8

typedef enum
{
    SPI_MODE0=0,      //SCPOL=0,SCPH=0
    SPI_MODE1,        //SCPOL=0,SCPH=1
    SPI_MODE2,        //SCPOL=1,SCPH=0
    SPI_MODE3,        //SCPOL=1,SCPH=1
} SPI_SCMOD_e;

typedef enum
{
	SPI_MINBYTE=0x03,
    SPI_1BYTE=0x07, //1byte
    SPI_2BYTE=0x0f,SPI_MAXBYTE=0x0f, //2byte
} SPI_DFS_e;


typedef enum
{
    SPI_TRXD=0, //Transmit & Receive
    SPI_TXD,    //Transmit Only
    SPI_RXD,    //Receive Only
//    SPI_EEPROM, //EEPROM Read
} SPI_TMOD_e;

typedef enum
{
    SPI0=0, //use spi 0
    SPI1,   //use spi 1
} SPI_INDEX_e;


typedef enum
{
    SPI_TX_COMPLETED = 1,
    SPI_RX_COMPLETED,
    SPI_TX_REQ_S,   //slave tx
    SPI_RX_DATA_S,  //slave rx
} SPI_EVT_e;

typedef struct _spi_evt_t
{
    uint8_t     id;
    SPI_EVT_e   evt;
    uint8_t*    data;
    uint8_t     len;
} spi_evt_t;

typedef void (*spi_hdl_t)(spi_evt_t* pevt);

typedef struct _spi_Cfg_t
{
    GpioPin_t   sclk_pin;
    GpioPin_t   ssn_pin;
    GpioPin_t   MOSI;
    GpioPin_t   MISO;
    uint32_t    baudrate;
    SPI_TMOD_e  spi_tmod;
    SPI_SCMOD_e spi_scmod;
    SPI_DFS_e   spi_dfsmod;
    bool        dma_tx_enable;
    bool        dma_rx_enable;
    bool        int_mode;
    bool        force_cs;
    bool        is_slave;
    spi_hdl_t   evt_handler;
} spi_Cfg_t;

typedef enum
{
    TRANSMIT_FIFO_EMPTY = 0x01,
    TRANSMIT_FIFO_OVERFLOW = 0x02,
    RECEIVE_FIFO_UNDERFLOW = 0x04,
    RECEIVE_FIFO_OVERFLOW = 0x08,
    RECEIVE_FIFO_FULL = 0x10,
} SPI_INT_STATUS_e;

void __attribute__((weak)) HalSpi0IRQHandler(void);
void __attribute__((weak)) HalSpi1IRQHandler(void);

ErrCode_t HalSpiInit(SPI_INDEX_e channel);
void HalSpiDfsSet(SPI_INDEX_e index, SPI_DFS_e mod);
ErrCode_t HalSpiMasterTransfer(AP_SSI_TypeDef* SPIx, SPI_TMOD_e mod, uint8_t* tx_buf, uint8_t* rx_buf, uint16_t len);
ErrCode_t HalSpiSlaveTxPrepare(AP_SSI_TypeDef* SPIx, uint8_t* tx_buf, uint16_t len);
ErrCode_t HalSpiSetIntMode(SPI_INDEX_e index, bool en);
bool HalSpiGetTransmitState(SPI_INDEX_e index);
ErrCode_t HalSpiMasterConfig(AP_SSI_TypeDef* SPIx, spi_Cfg_t *cfg);
ErrCode_t HalSpiSlaveConfig(AP_SSI_TypeDef* SPIx, spi_Cfg_t *cfg);
ErrCode_t HalSpiDeinit(SPI_INDEX_e index);
ErrCode_t HalSpiDmaSet(SPI_INDEX_e index, bool ten, bool ren);

#endif
